#include "../Base/stdafx.h"
#include "XmlLoader.h"
#include "../Base/GameEngine.h"
#include "../Base/StringUtil.h"
#include "XMLNode.h"
#include <boost/foreach.hpp>

XMLLoader::XMLLoader(): m_Loaded(false), m_CurrentNode(0)
{

}

XMLLoader::XMLLoader( const tstring& file ): m_Loaded(false), m_CurrentNode(0)
{
	Load(file);
}

XMLLoader::~XMLLoader()
{
	BOOST_FOREACH(XMLNode* node, m_Nodes) delete node;
}

void XMLLoader::Load( const tstring& file )
{
	tifstream input(file.c_str());
	if(!input)
	{
		LOG(_T("ERROR: Kan ") + file + _T(" niet inladen."));
	}else{
		tstring line;
		XMLSteps step = START;
		while(!input.eof())
		{
			tstring startElem = _T("");
			tstring temp1 = _T(""), temp2 = _T(""), text = _T("");

			getline(input, line);
			StringUtil::TrimWhiteSpace(line);
			
			for(int t = 0; t < (int)line.length(); ++t)
			{
				tstring letter = line.substr(t, 1);
				switch(step)
				{
				case START:
					// Skip first line
					t = line.length();
					step = BEGINELEM;
					break;

				case BEGINELEM:
					// Read the start element
					if(letter == _T("<"))
					{
						if(m_CurrentNode != 0)
							m_CurrentNode = m_CurrentNode->AddChild(new XMLNode());
						else
						{
							m_CurrentNode = new XMLNode();
							m_Nodes.push_back(m_CurrentNode);
						}
					} else	 if(letter == _T(" ")) {
						m_CurrentNode->SetStartElement(startElem);
						startElem = _T("");
						step = NAME;
					} else if(letter == _T(">")){
						m_CurrentNode->SetStartElement(startElem);
						startElem = _T("");
						step = TEXT;
					} else
						startElem += letter;
					break;

				case NAME:
					// Read the name
					if(letter == _T("="))
						step = VALUE;
					else
						temp1 += letter;
					break;

				case VALUE:
					// Read the value and add it to the node
					if(letter == _T(" ") || letter == _T(">") || letter == _T("/"))
					{
						temp2 = temp2.substr(1, temp2.size()-2);
						m_CurrentNode->AddValue(make_pair(temp1, temp2));
						temp1 = _T(""); temp2 = _T("");
						if(letter == _T(" "))
							step = NAME;
						else if(letter == _T(">"))
							step = TEXT;
						else
							step = ENDELEM;
					}else
						temp2 += letter;
					break;

				case TEXT:
					// Read the text between
					if(letter == _T("<"))
					{
						m_CurrentNode->SetText(text);
						text = _T("");
						step = ENDELEM;
					}else
						text += letter;
					break;

				case ENDELEM:
					// Goto Parent if exists
					if(letter != _T("/") && letter != _T(">"))
					{
						t-=2;
						step = BEGINELEM;
					}else{
						if(letter != _T(">"))
							t += m_CurrentNode->GetStartElem().length() + 1;

						m_CurrentNode = const_cast<XMLNode*>(m_CurrentNode->GetParent());
						step = TEXT;
					}
					break;
				}
			}
		}
		input.close();
		m_CurrentNode = m_Nodes.at(0);
		m_Loaded = true;
	}
}

const tstring& XMLLoader::GetStartElement() const
{
	return m_CurrentNode->GetStartElem();
}

const tstring& XMLLoader::GetValue(const tstring& key) const
{
	return m_CurrentNode->GetValue(key);
}

bool XMLLoader::Next()
{
	XMLNode* temp;
	temp = m_CurrentNode;
	m_CurrentNode = const_cast<XMLNode*>(m_CurrentNode->GetNextChild());
	if(m_CurrentNode == NULL)
	{
		do 
		{
			m_CurrentNode = const_cast<XMLNode*>(temp->GetParent());
			temp = m_CurrentNode;
			if(m_CurrentNode == NULL) return false;
			m_CurrentNode = const_cast<XMLNode*>(m_CurrentNode->GetNextChild());
		} while (m_CurrentNode == 0);
	}
	return true;
}

const XMLNode* XMLLoader::GetParent() const
{
	return m_CurrentNode->GetParent();
}